﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using ARR.Entities;
using DDF.Entity;
using ARR.UI.ArticlesService;
using ARR.Shared;
using ARR.UI.CategoriesService;


namespace ARR.UI.Models
{
    public interface ISalesMasterModel : IModelBase
    {
        ObservableCollection<ArticleSale> Sales { get; set; }

        ObservableCollection<ImporterResult> Results { get; set; }

        List<Category> Categories { get; set; }
        
        
        void Save();

        void LoadSales();

        void RunSalesValidations();

    }


    public class SalesMasterModel : ModelBase, ISalesMasterModel
    {
        public SalesMasterModel()
        {
            Sales = new ObservableCollection<ArticleSale>();
            Results = new ObservableCollection<ImporterResult>();

            LoadCategories();
        }


        public ObservableCollection<ArticleSale> Sales { get; set; }

        public ObservableCollection<ImporterResult> Results { get; set; }
        
        public List<Category> Categories { get; set; }

        public void Save()
        {
            var toSave = Sales.Where(x => x.GetEntityState() != EntityState.Original);

            ArticlesServiceClient service = new ArticlesServiceClient();

            try
            {
                service.SaveSales(toSave.ToList());
                service.Close();
            }
            catch
            {
                service.Abort();
                throw;
            }

        }

        public void LoadSales()
        {
            //using (ArticlesServiceClient service = new ArticlesServiceClient())
            //{

            //    var artSales = service.GetAllSales(WorkspaceData.Instance.RangeReview.Id)
            //                          .OrderBy(x => x.StoreName)
            //                          .ThenBy(x => x.Date)
            //                          .ThenBy(x => x.ArticleName);

            //    Sales = new ObservableCollection<ArticleSale>(artSales);
            //}
        }

        public void RunSalesValidations()
        {
            IList<ImporterResult> importerResults = new List<ImporterResult>();
            int count = 0;
            try
            {
                //Verifico si hay registros con margenes negativos.
                var negativeMargins = Sales.Where(x => x.GM < 0);  //TempArticleSalesRepository.Select(sale => sale.GM < 0);


                List<TheoreticalMargin> theoreticalMargins;
                List<CategoryMargin> categoryMargins;
                CategoriesServiceClient catService = new CategoriesServiceClient();
                try
                {
                    theoreticalMargins = catService.GetTheoreticalMargins(WorkspaceData.Instance.Country.Id);
                    catService.Close();
                }
                catch
                {
                    catService.Abort();
                    throw;
                }


                //Cargo los margenes por catgoria
                ArticlesServiceClient artService = new ArticlesServiceClient();
                try
                {
                    categoryMargins = artService.GetArticleSalesCategoryMargins(WorkspaceData.Instance.RangeReview.Id);
                    artService.Close();
                }
                catch
                {
                    artService.Abort();
                    throw;
                }


                foreach (var cat in categoryMargins)
                {
                    var tMargin = theoreticalMargins.SingleOrDefault(tm => tm.CategoryId == cat.Id);
                    if (tMargin != null)
                        cat.Margin = tMargin.Margin;

                    importerResults.Add(new ImporterResult
                    {
                        Category = ResultCategory.Validation,
                        Description = string.Format(Messages.MargenDeLaCategoria, cat.Name, cat.Margin),
                        ErrorType = (cat.Margin.HasValue && (cat.Margin <= 0 || cat.Margin == 1)) ? ErrorType.Warning : ErrorType.Information,
                        Id = count,
                        Workaround = Workaround.CategoryMargin,
                        Param1 = cat.Name,
                        Param2 = cat.Margin.ToString(),
                        ItemId = cat.Id
                    });
                }

                //Unidades en 0 y ventas o margen <> 0
                var unitsInZero = Sales.Where(sale => sale.Units == 0 && (sale.Sales != 0 || sale.GM != 0));

                foreach (var sale in unitsInZero)
                {
                    importerResults.Add(new ImporterResult
                    {
                        Category = ResultCategory.Validation,
                        Description = string.Format(Messages.UnidadesEnCeroConVentas, sale.ArticleName, sale.StoreName, sale.Date),
                        ErrorType = ErrorType.Warning,
                        Id = count,
                        Workaround = Workaround.UnitsIsZero,
                        Param1 = sale.Units.ToString(),
                        Param2 = sale.Sales.ToString(),
                        Param3 = sale.GM.ToString(),
                        ItemId = sale.Id
                    });
                }


                //Unidades <> 0 y ventas o margen en 0
                var salesOrMarginInZero = Sales.Where(sale => sale.Units > 0 && (sale.Sales == 0 || sale.GM == 0));

                foreach (var sale in salesOrMarginInZero)
                {
                    importerResults.Add(new ImporterResult
                    {
                        Category = ResultCategory.Validation,
                        Description = string.Format(Messages.VentasEnCeroConUnidades, sale.ArticleName, sale.StoreName, sale.Date),
                        ErrorType = ErrorType.Warning,
                        Id = count,
                        Workaround = Workaround.SalesOrMarginIsZero,
                        Param1 = sale.Units.ToString(),
                        Param2 = sale.Sales.ToString(),
                        Param3 = sale.GM.ToString(),
                        ItemId = sale.Id
                    });
                }

                //Unidades negativas 
                var negativeUnits = Sales.Where(sale => sale.Units < 0);

                foreach (var sale in negativeUnits)
                {
                    importerResults.Add(new ImporterResult
                    {
                        Category = ResultCategory.Validation,
                        Description = string.Format(Messages.UnidadesNegativas, sale.ArticleName, sale.StoreName, sale.Date),
                        ErrorType = ErrorType.Warning,
                        Id = count,
                        Workaround = Workaround.NegativeUnits,
                        Param1 = sale.Units.ToString(),
                        Param2 = sale.Sales.ToString(),
                        Param3 = sale.GM.ToString(),
                        ItemId = sale.Id
                    });
                }


                Results = new ObservableCollection<ImporterResult>(importerResults);

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void LoadCategories()
        {
            List<Category> categories = new List<Category>();

            CategoriesServiceClient categoryService = new CategoriesServiceClient();
            try
            {
                categories = categoryService.GetByLevels(2);
                categoryService.Close();
            }
            catch
            {
                categoryService.Abort();
                throw;
            }

            foreach (var category in categories.Where(x => x.Level == 2))
            {
                category.SubCategories = new List<Category>();
                category.SubCategories.AddRange(categories.Where(x => x.ParentId == category.Id));
            }
            Categories = categories.Where(x => x.Level == 2).OrderBy(x => x.Name).ToList();
        }


    }


    public class SalesMasterModelMock : MockModelBase, ISalesMasterModel
    {
        public SalesMasterModelMock()
        {
            Sales = new ObservableCollection<ArticleSale>();
            Results = new ObservableCollection<ImporterResult>();

            LoadSales();
        }

        public List<Category> Categories { get; set; }

        public ObservableCollection<ArticleSale> Sales { get; set; }

        public ObservableCollection<ImporterResult> Results { get; set; }


        public void Save()
        {
        }

        public void LoadSales()
        {
            Sales.Clear();

            Sales.Add(new ArticleSale { ArticleName = "AR0001", StoreName = "ST0001", Sales = 155.66M, GrossSales = 155.66M, GM = 25.12M, Units = 5, Price = 4 });
            Sales.Add(new ArticleSale { ArticleName = "AR0002", StoreName = "ST0001", Sales = 155.66M, GrossSales = 155.66M, GM = 25.12M, Units = 5, Price = 4 });
            Sales.Add(new ArticleSale { ArticleName = "AR0003", StoreName = "ST0001", Sales = 155.66M, GrossSales = 155.66M, GM = 25.12M, Units = 5, Price = 4 });
            Sales.Add(new ArticleSale { ArticleName = "AR0004", StoreName = "ST0001", Sales = 155.66M, GrossSales = 155.66M, GM = 25.12M, Units = 5, Price = 4 });
            Sales.Add(new ArticleSale { ArticleName = "AR0005", StoreName = "ST0001", Sales = 155.66M, GrossSales = 155.66M, GM = 25.12M, Units = 5, Price = 4 });


            foreach (ArticleSale sale in Sales)
            {
                sale.ChangeState(EntityState.Original);
            }
        }

        public void RunSalesValidations()
        {
            
        }

    }

}
